//
// Created by zhouwd on 2019/8/1.
//

#include "media_audio_play.h"

MediaAudioDecode *mediaAudioDecode;

int getPcm(void **pcm, size_t *pcm_size) {

    return mediaAudioDecode->getPcm(pcm, pcm_size);
}

void pcmBufferCallBack(SLAndroidSimpleBufferQueueItf bf, void *context) {
    void *buffer;

    size_t pcm_size;

    int ret = getPcm(&buffer, &pcm_size);

    ALOGE("pcmBufferCallBack, size=%d", pcm_size);

    if (nullptr != buffer && ret == 0) {
        SLresult result = (*bf)->Enqueue(bf, buffer, pcm_size);
        ALOGE("pcmBufferCallBack, result=%d", result);
    }
}


int _MEDIA_AUDIO_PLAY::init(const char *filename) {
    mediaAudioDecode = new MediaAudioDecode();
    mediaAudioDecode->init(filename);

    SLresult result;

    //调用全局方法创建一个引擎对象（OpenSL ES唯一入口）
    result = slCreateEngine(&engine_object, 0, NULL, 0, NULL, NULL);

    ALOGE("_MEDIA_AUDIO_PLAY > init > slCreateEngine > result > %d", result);

    //实例化这个对象
    result = (*engine_object)->Realize(engine_object, SL_BOOLEAN_FALSE);

    ALOGE("_MEDIA_AUDIO_PLAY > init > Realize > result > %d", result);

    //从这个对象里面获取引擎接口
    result = (*engine_object)->GetInterface(engine_object, SL_IID_ENGINE, &engine_engine);

    ALOGE("_MEDIA_AUDIO_PLAY > init > GetInterface > result > %d", result);
    //第二步，创建混音器
    const SLInterfaceID mids[1] = {SL_IID_ENVIRONMENTALREVERB};
    const SLboolean mreq[1] = {SL_BOOLEAN_FALSE};
    result = (*engine_engine)->CreateOutputMix(engine_engine, &outputMixObject, 1, mids, mreq);
    ALOGE("_MEDIA_AUDIO_PLAY > init > CreateOutputMix > result > %d", result);
    (void)result;

    result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
    ALOGE("_MEDIA_AUDIO_PLAY > init > Realize > result > %d", result);
    (void)result;

    result = (*outputMixObject)->GetInterface(outputMixObject, SL_IID_ENVIRONMENTALREVERB, &outputMixEnvironmentalReverb);
    ALOGE("_MEDIA_AUDIO_PLAY > init > GetInterface > result > %d", result);
    if (SL_RESULT_SUCCESS == result) {
        result = (*outputMixEnvironmentalReverb)->SetEnvironmentalReverbProperties(outputMixEnvironmentalReverb, &reverbSettings);
        (void)result;
    }

    // 第三步，配置PCM格式信息
    SLDataLocator_AndroidSimpleBufferQueue android_queue={SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,2};
    SLDataFormat_PCM pcm={
            SL_DATAFORMAT_PCM,//播放pcm格式的数据
            2,//2个声道（立体声）
            SL_SAMPLINGRATE_44_1,//44100hz的频率
            SL_PCMSAMPLEFORMAT_FIXED_16,//位数 16位
            SL_PCMSAMPLEFORMAT_FIXED_16,//和位数一致就行
            SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,//立体声（前左前右）
            SL_BYTEORDER_LITTLEENDIAN//结束标志
    };
    SLDataSource slDataSource = {&android_queue, &pcm};



    // 2、 配置 audio sink
    SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
    SLDataSink audioSnk = {&loc_outmix, NULL};

    const SLInterfaceID ids[3] = {SL_IID_BUFFERQUEUE, SL_IID_EFFECTSEND, SL_IID_VOLUME};
    const SLboolean req[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};

    result = (*engine_engine)->CreateAudioPlayer(engine_engine, &pcmPlayerObject, &slDataSource, &audioSnk, 3, ids, req);
    ALOGE("_MEDIA_AUDIO_PLAY > init > CreateAudioPlayer > result > %d", result);
    //初始化播放器
    result = (*pcmPlayerObject)->Realize(pcmPlayerObject, SL_BOOLEAN_FALSE);
    ALOGE("_MEDIA_AUDIO_PLAY > init > Realize > result > %d", result);
    //    得到接口后调用  获取Player接口
    result = (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_PLAY, &pcmPlayerPlay);
    ALOGE("_MEDIA_AUDIO_PLAY > init > GetInterface > result > %d", result);

    //    注册回调缓冲区 获取缓冲队列接口
    result = (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_BUFFERQUEUE, &pcmBufferQueue);
    ALOGE("_MEDIA_AUDIO_PLAY > init > GetInterface > result > %d", result);
    //缓冲接口回调
    result = (*pcmBufferQueue)->RegisterCallback(pcmBufferQueue, pcmBufferCallBack, NULL);
    ALOGE("_MEDIA_AUDIO_PLAY > init > RegisterCallback > result > %d", result);

    return 0;
}


_MEDIA_AUDIO_PLAY::_MEDIA_AUDIO_PLAY() {

}

_MEDIA_AUDIO_PLAY::~_MEDIA_AUDIO_PLAY() {

}



int _MEDIA_AUDIO_PLAY::startAudioPlay() {
    SLresult result;

    result = (*pcmPlayerPlay)->SetPlayState(pcmPlayerPlay, SL_PLAYSTATE_PLAYING);
    ALOGE("_MEDIA_AUDIO_PLAY > startAudioPlay > SetPlayState > result > %d", result);

    pcmBufferCallBack(pcmBufferQueue, nullptr);

    return 0;
}

int _MEDIA_AUDIO_PLAY::stopAudioPlay() {

    SLresult result;

    result = (*pcmPlayerPlay)->SetPlayState(pcmPlayerPlay, SL_PLAYSTATE_STOPPED);
    ALOGE("_MEDIA_AUDIO_PLAY > stopAudioPlay > SetPlayState > result > %d", result);

    return 0;
}


